package com.atguigu.tingshu.common.aspect;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.anno.GuiGuLogin;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component          // 把当前类纳入到spring容器中
@Aspect             // 定义当前这个类就是一个切面类
@Slf4j
public class GuiGuLoginAspect {         // 定义成一个切面类

    @Autowired
    private RedisTemplate<String , String> redisTemplate ;

    @Around("@annotation(guiGuLogin)")
    @SneakyThrows
    public Object around(ProceedingJoinPoint proceedingJoinPoint , GuiGuLogin guiGuLogin) {
        //1.获取token
        //1.1、获取ServletRequestAttributes对象（调用RequestContextHolder.getReqAtt方法）
        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //1.2、从ServletRequestAttributes获取HttpServletRequest
        HttpServletRequest request = requestAttributes.getRequest();
        //1.3、获取当前请求头中的token
        String token = request.getHeader("token");
        //2. 判断是否是受保护的
        if (guiGuLogin.required()){
            // 需要
            // 判断是否携带token
            if (!StringUtils.isEmpty(token)){
                // 携带了token
                String userInfoJSON =  redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX + token);
                //  判断对象是否为空
                if (StringUtils.isEmpty(userInfoJSON)){
                    // 是空的 抛出异常信息
                    throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
                }
                //不是空的 JSON 格式改变 获取 userInfo 对象 将用户信息存储到ThreadLocal中
                UserInfo userInfo = JSON.parseObject(userInfoJSON, UserInfo.class);
                AuthContextHolder.setUserId(userInfo.getId());
                AuthContextHolder.setUsername(userInfo.getNickname());
                // 判断是否携带正确信息
            }else {
                // 未携带token
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
        }else {
            // 不需要受保护
            // 是否携带了token
            if (!StringUtils.isEmpty(token)){
                // 携带了 token
                // 在redis里获取 userInfo的JSON格式
                String userInfoJSON =  redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX + token);
                // 判断是否存在用户数据
                if (!StringUtils.isEmpty(userInfoJSON)){
                    // 存在 是真token 将用户信息存储到ThreadLocal中
                    UserInfo userInfo = JSON.parseObject(userInfoJSON, UserInfo.class);
                    AuthContextHolder.setUserId(userInfo.getId());
                    AuthContextHolder.setUsername(userInfo.getNickname());
                }
                // 假token
            }
            //未携带token 放行
        }
        return proceedingJoinPoint.proceed();
    }

}




















